package cece.config;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Created by 54110 on 2020/5/18.
 */
@Configuration
public class ShiroConfig {

    /**
     * 配置过滤器拦截请求
     *
     * @param defaultWebSecurityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // 如果认证没有通过配置跳转的页面
        // shiroFilterFactoryBean.setLoginUrl("/user/toLogin");
        // 设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        Map<String, String> map = new LinkedHashMap<>();
        // map.put("/main","authc");  //必须登录才可访问
        // map.put("/findAll","perms[user_edit]");//只有特定权限（“user_edit”）的用户登录后才可访问
        // map.put("/two","perms[user_forbidden]");//只有特定权限（“user_forbidden”）的用户登录后才可访问
        // shiroFilterFactoryBean.setLoginUrl("/login");//设置登录页（匿名）
        // shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");//权限不足的错误提示页
        // 表示所有请求都拦截 参数1：拦截路径。参数2：过滤器的名字
        /**
         * 常见过滤器名称以及含义
         * authc：认证过滤器
         *      /** 与 /* 的区别?
         *          /* 匹配当前一级的目录  127.0.0.1:8080/cece
         *          /** 匹配当前一级目录以及后面所有的子目录
         * anon:表示所请求的当前路径没有认证也可以访问（匿名访问）
         *      map.put("/toIndex","anon");
         * logout：登出过滤器
         *      map.put("/logout","logout");
         * perms:权限控制
         * roles:具有某一个角色才能访问某一个地址
         *
         * /** 这个配置必须放置最后一个
         */
        map.put("/user/*", "anon");
        // map.put("/user/userRegister", "anon");
        // map.put("/user/toLogin", "anon");
//        map.put("authc", new MyAuthenticationFilter());
        //  map.put("/**", "authc"); //所有的请求都必须在用户认证了之后才能访问
        //  shiroFilterFactoryBean.setFilterChainDefinitionMap(map);//装配拦截策略
        return shiroFilterFactoryBean;
    }

    //    配置安全管理器（注入Realm对象）
    @Bean(name = "defaultWebSecurityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("myShiroRealm") MyShiroRealm myShiroRealm) {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(myShiroRealm);
        return defaultWebSecurityManager;
    }

    /**
     * 配置Realm
     *
     * @return
     */
    @Bean(name = "myShiroRealm")  //使用该注解是的Realm对象由spring容器管理
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm shiroRealm = new MyShiroRealm();
        shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return shiroRealm;
    }


    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        // 设置密码散列的方法
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        // 设置散列的次数
        hashedCredentialsMatcher.setHashIterations(1);
        return hashedCredentialsMatcher;
    }


    //开启shiro注解模式

    /**
     * 开启Shiro注解(如@RequiresRoles,@RequiresPermissions),
     * 需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    /**
     * 开启aop注解支持
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
        return authorizationAttributeSourceAdvisor;
    }
}
